package org.no_ip.martin_springwald.google.api.extension.docs;

import com.google.api.gwt.shared.AuthScope;
import com.google.gwt.gdata.client.GDataRequestParameters;
import com.google.gwt.gdata.client.GoogleService;
import com.google.gwt.gdata.client.impl.Callback;
import com.google.gwt.gdata.client.impl.MapString;
import com.google.gwt.http.client.URL;

/**
 * DocumentsService - Google Docs Service Extension
 * 
 * @.dependencies gwt-gdata, gwt-google-apis, GWT SDK 2.4
 * @author Martin Springwald (martin_springwald at web.de)
 * @license MIT (see LICENSE.TXT)
 * @version 1.0.2 public
 */
public class DocumentsService extends GoogleService {
	
	/** SERVICE_NAME: <br/> Google Service name */
	public static final String SERVICE_NAME = "writely"; //$NON-NLS-1$
	
	/** GDATA_VERSION: <br/> Google Protocol version */
	public static final String GDATA_VERSION = "3"; //$NON-NLS-1$

	/** DocumentListAuthScope: <br/> Authorization scopes for DocumentList API */
	public enum DocumentListAuthScope implements AuthScope {
		/** DOCS: <br/> Google Authorization Scope for Docs */
		DOCS("https://docs.google.com/feeds/"), //$NON-NLS-1$
		/** FILES: <br/> Google Authorization Scope for Files */
		FILES("https://docs.googleusercontent.com/"), //$NON-NLS-1$
		/** SPREADSHEETS: <br/> Google Authorization Scope for Spreadsheets */
		SPREADSHEETS("https://spreadsheets.google.com/feeds/"); //$NON-NLS-1$
		private final String scope;
		private DocumentListAuthScope(String scope) { this.scope = scope; }
		@Override public String getScope() { return scope; }
	}

	/** useOAuth2: <br/> Stores authorization token (OAuth2) */
    public final native String useOAuth2() /*-{ this.authToken = $wnd.gapi.auth.getToken().access_token; }-*/;
	/** getOAuth2Token: <br/> Get stored authorization token (OAuth2) */
    private final native String getOAuth2Token() /*-{ if (this.authToken) { return this.authToken; }  else { return null; } }-*/;

    /** buildQueryString: <br/> construct Query URI from DocumentsListQuery Object */
	private String buildQueryString(DocumentsListQuery query) {
		// replace userId and docId placeholders
		String uri = ((query.getUri()==null)?query.getType().getUri():query.getUri()).replace("%USER%", URL.encodePathSegment(query.getUserId())); if (query.getDocId()!=null) uri = uri.replace("%DOCID%", URL.encodePathSegment(query.getDocId())); //$NON-NLS-1$ //$NON-NLS-2$
		// set protocol version and authorization token
		uri = uri + "?v="+DocumentsService.GDATA_VERSION+((this.getOAuth2Token()!=null)?"&access_token="+this.getOAuth2Token():""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		// append additional parameters
		MapString queryParam = query.getAdditional(); for (int i=0; i<queryParam.keys().length; i++) { uri = uri + "&" + queryParam.keys()[i] + "=" + URL.encodeQueryString(queryParam.get(queryParam.keys()[i])); } //$NON-NLS-1$ //$NON-NLS-2$
		// return constructed query URI
		return uri;
	}

    // read functions
	public final void getMetadataEntry(DocumentsListQuery query, DocumentsListMetadataEntryCallback callback) { query.setType(DocumentsListQuery.Type.METADATA); this.getEntry(this.buildQueryString(query), callback, DocumentsListMetadataEntry.getConstructor(), true, null); }
	public final void getMetadataEntry(DocumentsListQuery query, DocumentsListMetadataEntryCallback callback, GDataRequestParameters parameters) { query.setType(DocumentsListQuery.Type.METADATA); this.getEntry(this.buildQueryString(query), callback, DocumentsListMetadataEntry.getConstructor(), true, parameters); }
	public final void getRevisionFeed(DocumentsListQuery query, DocumentsListRevisionFeedCallback callback) { this.getFeed(this.buildQueryString(query), callback, DocumentsListRevisionFeed.getConstructor(), true, null); }
	public final void getRevisionFeed(DocumentsListQuery query, DocumentsListRevisionFeedCallback callback, GDataRequestParameters parameters) { this.getFeed(this.buildQueryString(query), callback, DocumentsListRevisionFeed.getConstructor(), true, parameters); }
	public final void getChangesFeed(DocumentsListQuery query, DocumentsListChangesFeedCallback callback) { query.setType(DocumentsListQuery.Type.CHANGES); this.getFeed(this.buildQueryString(query), callback, DocumentsListChangesFeed.getConstructor(), true, null); }
	public final void getChangesFeed(DocumentsListQuery query, DocumentsListChangesFeedCallback callback, GDataRequestParameters parameters) { query.setType(DocumentsListQuery.Type.CHANGES); this.getFeed(this.buildQueryString(query), callback, DocumentsListChangesFeed.getConstructor(), true, parameters); }
	public final void getBatchFeed(DocumentsListQuery query, DocumentsListBatchFeedCallback callback) { this.getFeed(this.buildQueryString(query), callback, DocumentsListBatchFeed.getConstructor(), true, null); }
	public final void getBatchFeed(DocumentsListQuery query, DocumentsListBatchFeedCallback callback, GDataRequestParameters parameters) { this.getFeed(this.buildQueryString(query), callback, DocumentsListBatchFeed.getConstructor(), true, parameters); }
	public final void getBatchAclFeed(DocumentsListQuery query, DocumentsListBatchAclFeedCallback callback) { this.getFeed(this.buildQueryString(query), callback, DocumentsListBatchAclFeed.getConstructor(), true, null); }
	public final void getBatchAclFeed(DocumentsListQuery query, DocumentsListBatchAclFeedCallback callback, GDataRequestParameters parameters) { this.getFeed(this.buildQueryString(query), callback, DocumentsListBatchAclFeed.getConstructor(), true, parameters); }
	public final void getArchiveEntry(DocumentsListQuery query, DocumentsListArchiveEntryCallback callback) { query.setType(DocumentsListQuery.Type.ARCHIVE); this.getEntry(this.buildQueryString(query), callback, DocumentsListArchiveEntry.getConstructor(), true, null); }
	public final void getArchiveEntry(DocumentsListQuery query, DocumentsListArchiveEntryCallback callback, GDataRequestParameters parameters) { query.setType(DocumentsListQuery.Type.ARCHIVE); this.getEntry(this.buildQueryString(query), callback, DocumentsListArchiveEntry.getConstructor(), true, parameters); }
	public final void getAclFeed(DocumentsListQuery query, DocumentsListAclFeedCallback callback) { this.getFeed(this.buildQueryString(query), callback, DocumentsListAclFeed.getConstructor(), true, null); }
	public final void getAclFeed(DocumentsListQuery query, DocumentsListAclFeedCallback callback, GDataRequestParameters parameters) { this.getFeed(this.buildQueryString(query), callback, DocumentsListAclFeed.getConstructor(), true, parameters); }
	public final void getFeed(DocumentsListQuery query, DocumentsListFeedCallback callback) { query.setType(DocumentsListQuery.Type.LIST); this.getFeed(this.buildQueryString(query), callback, DocumentsListFeed.getConstructor(), true, null); }
	public final void getFeed(DocumentsListQuery query, DocumentsListFeedCallback callback, GDataRequestParameters parameters) { query.setType(DocumentsListQuery.Type.LIST); this.getFeed(this.buildQueryString(query), callback, DocumentsListFeed.getConstructor(), true, parameters); }
	public final void getDocumentFeed(DocumentsListQuery query, DocumentsListFeedCallback callback) { query.setType(DocumentsListQuery.Type.DOCUMENT); this.getFeed(this.buildQueryString(query), callback, DocumentsListFeed.getConstructor(), true, null); }
	public final void getDocumentFeed(DocumentsListQuery query, DocumentsListFeedCallback callback, GDataRequestParameters parameters) { query.setType(DocumentsListQuery.Type.DOCUMENT); this.getFeed(this.buildQueryString(query), callback, DocumentsListFeed.getConstructor(), true, parameters); }
	
	// write functions
	/** insertDocumentEntry: <p>Inserts DocumentsList entry and returns to callback</p> */
	public final void insertDocumentEntry(String uri, DocumentsListEntry entry, DocumentsListEntryCallback callback) { this.insertEntry(uri, entry, callback, DocumentsListEntry.getConstructor()); }
	/** updateDocumentEntry: <p>Updates DocumentsList entry and returns to callback</p> */
	public final void updateDocumentEntry(String uri, DocumentsListEntry entry, DocumentsListEntryCallback callback) { this.updateEntry(uri, entry, callback, DocumentsListEntry.getConstructor(), null); }
	/** updateDocumentEntry: <p>Updates DocumentsList entry and returns to callback</p> */
	public final void updateDocumentEntry(String uri, DocumentsListEntry entry, DocumentsListEntryCallback callback, GDataRequestParameters parameters) { this.updateEntry(uri, entry, callback, DocumentsListEntry.getConstructor(), parameters); }
	/** deleteDocumentEntry: <p>Deletes DocumentsList entry and returns to callback</p> */
	public final void deleteDocumentEntry(String uri, DocumentsListEntryCallback callback, GDataRequestParameters parameters) { this.deleteEntry(uri, callback, parameters); }
	/** deleteDocumentEntry: <p>Deletes DocumentsList entry and returns to callback</p> */
	public final void deleteDocumentEntry(String uri, DocumentsListEntryCallback callback) { this.deleteEntry(uri, callback); }

	// constructors
	/**
	 * newInstance: <p>Creates new Docs Service instance.</p>
	 * @param String applicationName
	 * @return GoogleService
	 */
	public static native DocumentsService newInstance(String applicationName) /*-{ return new $wnd.google.gdata.client.GoogleService(this.SERVICE_NAME, applicationName); }-*/;
	protected DocumentsService() { }

}